package com.message.api.base.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.annotation.SysLog;
import com.base.annotation.Unsecured;
import com.base.context.Context;
import com.base.context.ContextHolder;
import com.base.helper.BaseController;
import com.base.helper.DateUtils;
import com.base.helper.FileUploadUtils;
import com.base.helper.Result;
import com.message.api.base.entity.EnAttachment;
import com.message.api.base.service.EnAttachmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mzl
 * @since 2020-07-17
 */
@Api(tags = "附件")
@RestController
@RequestMapping("/enAttachment")
public class EnAttachmentController extends BaseController {

    private static final Logger              LOG = LoggerFactory.getLogger(EnAttachmentController.class);
    @Autowired
    private              EnAttachmentService entityService;

    @SysLog(action = "enAttachment:findByPage", value = "附件管理：附件列表")
    @ApiOperation(value = "分页查询附件", notes = "分页查询附件")
    @RequestMapping(method = RequestMethod.GET)
    @ApiImplicitParams({@ApiImplicitParam(name = "size", value = "分页大小", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面：从1开始", paramType = "query")})
    public Result<IPage<EnAttachment>> findByPage(final EnAttachment example, final Page page) {
        IPage<EnAttachment> records = entityService.page(example, page);
        return new Result(true, records);
    }

    @SysLog(action = "enAttachment:delete", value = "附件管理：删除")
    @ApiOperation(value = "删除附件")
    @RequestMapping(value = "{id}", method = {RequestMethod.DELETE})
    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
    public Result delete(@PathVariable final Integer id) {
        entityService.removeById(id);
        return new Result(true, "成功删除附件", null);
    }

    @SysLog(action = "enAttachment:one", value = "附件管理：查询")
    @ApiOperation(value = "查询单个附件")
    @RequestMapping(value = "{id}", method = {RequestMethod.GET})
    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
    public Result one(@PathVariable final Integer id) {
        EnAttachment entity = entityService.getById(id);
        return new Result(true, entity);
    }

    @SysLog(action = "enAttachment:add", value = "附件管理：添加")
    @ApiOperation(value = "添加附件")
    @RequestMapping(method = {RequestMethod.POST})
    public Result add(@Valid @RequestBody final EnAttachment entity) {
        entityService.save(entity);
        return new Result(true, "成功保存附件", null);
    }

    @SysLog(action = "enAttachment:update", value = "附件管理：修改")
    @ApiOperation(value = "修改附件")
    @RequestMapping(method = {RequestMethod.PUT})
    public Result update(@Valid @RequestBody final EnAttachment entity) {
        if (null == entity.getId()) {
            throw new RuntimeException("id不能为空");
        }
        entityService.updateById(entity);
        return new Result(true, "成功修改附件", null);
    }

    @SysLog(action = "enAttachment:all", value = "附件管理：全部附件")
    @ApiOperation(value = "全部附件")
    @RequestMapping(value = "all", method = RequestMethod.GET)
    public Result<List<EnAttachment>> all(EnAttachment example) {
        List<EnAttachment> entitys = entityService.list(example);
        if (null != entitys) {
            return new Result<>(true, entitys);
        }
        return new Result<>(true, Collections.emptyList());
    }

    @Unsecured
    @ApiOperation(value = "文件上传, 返回文件信息")
    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public Result<EnAttachment> upload(@RequestParam("file") MultipartFile file) {
        Context context = ContextHolder.currentContext();
        String  oriname = file.getOriginalFilename();
        try {
            String convertedName = new String(oriname.getBytes("ISO8859_1"), "UTF-8");
            long   size          = file.getSize();
            LOG.info("原文件名：{}, 大小: {}", convertedName, size);
            //
            String code     = UUID.randomUUID().toString().replaceAll("-", "");
            String filePath = FileUploadUtils.uploadFile(file, DateUtils.date(new Date(), "yyyyMMdd"), code);
            if (null == filePath) {
                throw new RuntimeException("保存文件失败");
            }
            EnAttachment enAttachment = new EnAttachment();
            enAttachment.setUserid(context.currentUser().getId());
            enAttachment.setName(convertedName);
            enAttachment.setType(file.getContentType());
            enAttachment.setPath(filePath);
            enAttachment.setCode(code);
            enAttachment.setSize(size + "");
            enAttachment.setCreatetime(new Date());
            enAttachment.setState("1");
            entityService.save(enAttachment);
            enAttachment = entityService.findByCode(code);
            return new Result(true, enAttachment);
        } catch (Exception e) {
            LOG.error("保存文件失败", e);
            return new Result(false, "上传文件失败", e.getMessage());
        }
    }

    @Unsecured
    @ApiOperation(value = "文件下载")
    @RequestMapping(value = "download/{id}", method = RequestMethod.GET)
    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
    public Result<Void> download(@PathVariable("id") final Integer id, HttpServletResponse response) {
        EnAttachment enAttachment = entityService.getById(id);
        if (null == enAttachment || "0".equals(enAttachment.getState())) {
            throw new RuntimeException("没有找到id对应的对象");
        }
        File                file   = new File(enAttachment.getPath());
        byte[]              buffer = new byte[1024];
        FileInputStream     fis    = null;
        BufferedInputStream bis    = null;
        try (OutputStream out = response.getOutputStream();) {
            response.setContentType(enAttachment.getType());
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=\"" +
                    new String((enAttachment.getName()).getBytes("utf-8"), "ISO8859_1") + "\"");
            // 将创建的Excel对象利用二进制流的形式强制输出到客户端去
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            int i = bis.read(buffer);
            while (i != -1) {
                out.write(buffer);
                i = bis.read(buffer);
            }
            // 强制将数据从内存中保存
            out.flush();
        } catch (IOException e) {
            return new Result<>(false, "文件下载失败", e.getMessage());
        }
        return new Result<>(true, "文件下载完成", null);
    }

    @Unsecured
    @ApiOperation(value = "批量文件下载")
    @RequestMapping(value = "downloadFiles/{ids}", method = RequestMethod.GET)
    @ApiImplicitParam(name = "ids", value = "附件ID", required = true, paramType = "path")
    public void downloadFiles(@PathVariable("ids") final List<Integer> ids, HttpServletResponse response) {
        if (null == ids || ids.size() == 0) {
            LOG.error("下载错误", "没有找到id");
        }
        List<EnAttachment> enAttachments = entityService.findByIds(ids);
        Map<String, File>  files         = new HashMap<>();
        for (EnAttachment enAttachment : enAttachments) {
            files.put(enAttachment.getName(), new File(enAttachment.getPath()));
        }
        ZipOutputStream zos   = null;
        ZipEntry        entry = null;
        FileInputStream in    = null;
        try (OutputStream out = response.getOutputStream();) {
            response.setContentType("application/x-zip-compressed");
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=\"" +
                    new String(("附件" + DateUtils.date(new Date()) + ".zip").getBytes("utf-8"), "ISO8859_1") + "\"");
            zos = new ZipOutputStream(out);
            for (String fileName : files.keySet()) {
                byte[] buffer = new byte[1024];
                int    len;
                //创建zip实体（一个文件对应一个ZipEntry）
                entry = new ZipEntry(fileName);
                in = new FileInputStream(files.get(fileName));
                zos.putNextEntry(entry);
                //文件流循环写入ZipOutputStream
                while ((len = in.read(buffer)) != -1) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            zos.close();
        } catch (Exception e) {
            LOG.error("批量下载错误", e.getMessage());
        }
    }

}

